package devops.katas.integrationtestingwithtestcontainers;

import org.assertj.core.api.BDDAssertions;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.PostgreSQLContainer;

import java.util.List;

import static io.restassured.RestAssured.when;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.equalTo;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(initializers = {IntegrationtestingwithtestcontainersApplicationIT.Initializer.class})
public class IntegrationtestingwithtestcontainersApplicationIT {

	@ClassRule
	public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres")
			.withDatabaseName("postgres")
			.withUsername("postgres")
			.withPassword("docker");

	@Autowired
	private CustomerRepository customerRepository;

	@Value("http://localhost:${local.server.port}")
    private String baseUrl;

    @Test
	public void should_have_customers() {
		List<Customer> all = customerRepository.findAll();

		BDDAssertions.then(all.size()).isEqualTo(6);
		BDDAssertions.then(all.get(0).getFirstName()).isEqualTo("First1");
		BDDAssertions.then(all.get(0).getLastName()).isEqualTo("Last1");
	}

	@Test
	public void should_return_200_with_expected_customers() {
		when()
            .get(baseUrl + "/customers").
        then()
            .statusCode(200)
                .body("size", is(6))
                .body("[0].firstName", equalTo("First1"))
                .body("[0].lastName", equalTo("Last1"));
	}

	static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
		@Override
		public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
			TestPropertyValues.of(
					"spring.datasource.url=" + postgreSQLContainer.getJdbcUrl(),
					"spring.datasource.username=" + postgreSQLContainer.getUsername(),
					"spring.datasource.password=" + postgreSQLContainer.getPassword()
			).applyTo(configurableApplicationContext.getEnvironment());
		}
	}
}
